from decimal import Decimal
from django.core.paginator import Paginator
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from goods.models import SKU
from django import http

from meiduo_mall.utils.log import logger_out
from meiduo_mall.utils.response_code import RETCODE
from users.models import Address
from meiduo_mall.utils.login import LoginRequiredMixin
from datetime import datetime
from . import models
from django.db import transaction
from .models import OrderInfo, OrderGoods

import json
import time


# 展现页面订单
class OrdersSettleView (LoginRequiredMixin, View):
    def get(self, request):
        # 获取用户
        user = request.user
        # 获取用户的id
        try:
             address = Address.objects.filter(user_id=user.id, is_deleted= False)
        except Exception as e:
            logger_out.warning(e)
            address = []
        # 获取redis中查出被选中的商品
        redis_cli = get_redis_connection('carts')
        redis_dict_list = redis_cli.hgetall('cart%d' % user.id)
        redis_set_list = redis_cli.smembers('selected%d' % user.id)
        carts = {}
        # 判断是否被选中
        for sku_id in redis_set_list:
            carts[int(sku_id)] = int(redis_dict_list[sku_id])

        # 获取所有的商品
        skus = SKU.objects.filter(id__in=carts.keys())

        # 可以计算数量和总价
        total_count = 0
        total_amount = Decimal(0.00)
        for sku in skus:
            sku.count = carts[sku.id]
            sku.amount = sku.count * sku.price
            total_count += sku.count
            total_amount += sku.amount

        freight = Decimal('10.00')
        context = {
            'addresses': address,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight
        }
        return render(request, 'place_order.html', context)


# 表单提交确定支付
class OrderCommitView (LoginRequiredMixin, View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        if not all([address_id, pay_method]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数不完整'})
        if int(pay_method) not in [1, 2]:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '支付方式无效'})
        try:
            addredss = Address.objects.filter(id=address_id, is_deleted=False)
        except Exception as e:
            logger_out.warning(e)
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '地址id错误！'})

        # 开启事物，禁止自动提交
        with transaction.atomic():
            # 开启事务
            sid = transaction.savepoint()

            user = request.user
            now = datetime.now()
            # 1.查询购物车中选中的商品redis中的hash表和集合
            # 2.创建订单基本信息
            # 3.查询商品对象
            # 4.遍历，如果库存不够，则返回提示说商品数量不够。修改sku中的数量。创建order_goods中的订单商品。计算总数量和总价。
            # 5. 删除redis中的数据

            # 1.查询购物车中选中的商品redis中的hash表和集合
            redis_cli = get_redis_connection('carts')
            cart_dict_bytes = redis_cli.hgetall('cart%d' % user.id)
            cart_dict_int = {int(sku_id): int(count) for sku_id, count in cart_dict_bytes.items()}
            cart_set_bytes = redis_cli.smembers('selected%d' % user.id)
            cart_set_int = [int(sku_id) for sku_id in cart_set_bytes]
            # 2.创建订单基本信息 id用时间加sku_id
            # now.strftime:将time结构转换为指定格式的字符串。
            # now.strptime:将指定格式的字符串转为time结构。
            order_id = '%s%09d' % (now.strftime('%Y%m%d%H%M%S'), user.id)
            total_count = 0
            total_amount = 0
            if int(pay_method) == 1:
                status = 1
            elif int(pay_method) == 2:
                status = 2
            # 3.查询商品对象)
            try:
                orderinfo = models.OrderInfo.objects.create(order_id=order_id,
                                                            user_id=user.id,
                                                            address_id=address_id,
                                                            total_count=total_count,
                                                            total_amount=total_amount,
                                                            freight=10,
                                                            pay_method=pay_method,
                                                            status=status, )
            except Exception as e:
                logger_out.warning(e)
                transaction.savepoint_rollback(sid)
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '重复提交购物车中的商品1'})
            # 3.查询商品对象
            skus = SKU.objects.filter(id__in=cart_set_int)
            # 4.遍历进行处理
            for sku in skus:
                cart_count = cart_dict_int.get(sku.id)
                if cart_count > sku.stock:
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '%s商品库存不足！！' % sku.name})
                # sku.stock -= cart_count
                # sku.sales += cart_count
                # 4.2使用乐观锁进行修改
                stock_old = sku.stock
                stock_new = sku.stock - cart_count
                sales_new = sku.sales + cart_count

                result = SKU.objects.filter(pk=sku.id, stock=stock_old).update(stock=stock_new, sales=sales_new)
                # result表示sql语句修改数据的个数
                if result == 0:
                    # 库存发生变化，未成功购买
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '服务器忙，请稍候重试'})

                order_sku = models.OrderGoods.objects.create(order_id=order_id,
                                                              sku_id=sku.id,
                                                              count=cart_count,
                                                              price=sku.price,
                                                              )
                # 计算商品总数量和总价格
                total_count += cart_count
                total_amount += total_count * sku.price
                # 跳出该循环
            # 保存到orderinfo
            orderinfo.total_count = total_count
            orderinfo.total_amount = total_amount + 10
            orderinfo.save()

            # 提交事务
            transaction.savepoint_commit(sid)
        # 删除reids中的数据
        try:
            redis_cli.hdel('cart%d' % user.id, *cart_set_int)
            redis_cli.srem('selected%d' % user.id, *cart_set_int)
        except Exception as e:
            logger_out.warning(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '重复提交购物车中的商品2'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'order_id': order_id})


# 订单提交成功
class OrderSuccessView (View):
    def get(self, request):
        # order_id = undefined & payment_amount = 11398 & pay_method = 2
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')
        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method,
        }
        return render(request, 'order_success.html', context)


# 支付成功页面
class OrderInfoView (View):
    def get(self, request, page_num):
        # 查询当前登录用户的所有订单,
        order_list = request.user.orders.exclude(total_count=0).order_by('-create_time')
        # 分页
        paginator = Paginator(order_list, 4)
        # 获取当前页面的对象
        page = paginator.page(page_num)

        # 遍历当前页面的数据，转换为页面中所需要的数据
        order_list2 = []
        for order in page:
            # 获取当前订单中的所有订单商品
            detail_list = []
            for detail in order.skus.all():
                detail_list.append({'default_image_url': detail.sku.default_image,
                                    'name': detail.sku.name,
                                    'price': detail.price,
                                    'count': detail.count,
                                    'total_amount': detail.price*detail.count, })
            order_list2.append({
                    'create_time': order.create_time,
                    'order_id': order.order_id,
                    'details': detail_list,
                    'total_amount': order.total_amount,
                    'freight': order.freight,
                    'status': order.status,
                })
        context = {
            'page': order_list2,
            'page_num': page_num,
            'total_page': paginator.num_pages,
        }
        return render(request, 'user_center_order.html', context)


# 展示用户评论订单
class OrdercommentView (View):
    def get(self, request):
        # http://www.meiduo.site:8000/orders/comment/?order_id=20190610141856000000036
        order_id = request.GET.get('order_id')
        # 筛选出当前用户的订单商品的详细列表
        orderinfor = OrderInfo.objects.get(order_id=order_id, user_id=request.user.id)

        skus = []

        for detail in orderinfor.skus.filter(is_commented=False):
            skus.append({
                'name': detail.sku.name,
                'price': str(detail.price),
                'default_image_url': detail.sku.default_image.url,
                'sku_id': detail.sku.id,
                'order_id': detail.order_id,
            })
        context = {
            "skus": skus,
        }
        return render(request, 'goods_judge.html', context=context)

    def post(self, request):
        # 接受
        dict_rec = json.loads(request.body.decode())
        order_id = dict_rec.get('order_id')
        sku_id = dict_rec.get('sku_id')
        comment = dict_rec.get('comment')
        score = dict_rec.get('score')
        is_anonymous = dict_rec.get('is_anonymous')
        # 验证
        # {sku_id: 15, comment: "你是最美丽的货物啊！我爱你", score: 5, is_anonymous: true}
        if not all([order_id, sku_id, comment, score]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数不完整'})
        if not isinstance(is_anonymous, bool):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '匿名类型的参数错误'})
        # 处理
        try:
            ordergood = OrderGoods.objects.get(order_id=order_id, sku_id=sku_id)
        except Exception as e:
            logger_out.warning(e)
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '没有找到该商品！'})
        # 在ordergood里面保存评论，分数和其他，
        ordergood.comment = comment
        ordergood.score = score
        ordergood.is_anonymous = is_anonymous
        ordergood.is_commented = True
        ordergood.save()
        # 获取商品sku,并让其库存加1
        sku = SKU.objects.get(id=int(sku_id))
        sku.comments += 1
        sku.save()
        print(sku.comments)
        # 如果当前订单号的商品都评价完成，应该将订单信息表的状态status设置为5：完成
        try:
            orders = OrderInfo.objects.get(order_id=order_id, user_id=request.user.id)
        except Exception as e:
            logger_out.warning(order_id)
            logger_out.warning(request.user.id)
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '没有找到该商品！'})
        bool_commit_status = True
        for detail in orders.skus.all():
            if not detail.is_commented:
                bool_commit_status = False
        if bool_commit_status:
            orders.status = 5
            orders.save()
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


class CommentDetailView (View):
    def get(self, request, sku_id):
        if not sku_id:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': 'sku_id参数错误！'})
        ordergoods = OrderGoods.objects.filter(sku_id=sku_id)
        goods_comment_list = []
        for detail in ordergoods:
            if not detail.is_anonymous:
                name_temp = detail.order.user.username
            else:
                name_temp = '******'
            goods_comment_list.append({'default_image_url': detail.sku.default_image.url,
                                       'username': name_temp,
                                       'comments': detail.comment,
                                       'score': detail.score,
                                       })
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok', 'goods_comment_list': goods_comment_list})
